
<pre>
  <script>
    //  JavaScript 词法和语法的代码分析
    // 利用正则文法 表示产生式
  
    let xregexp = {
      InputElement: "<Whitespace>|<LineTerminator>|<Comments>|<Token>",
      Whitespace: / /,
      LineTerminator: /\n/,
      Comments: /\/\*([^*]|\*[^\/])*\*\/|\/\/[^\n]*/,
      Token: "<Literal>|<Keywords>|<Identifer>|<Punctuator>",
      Literal: "<NumbericLiteral>|<BooleanLiteral>|<StringLiteral>|<NullLiteral>",
      NumbericLiteral: /([1-9][0-9]*|0)(\.[0-9]*)?|\.[0-9]+/,
      BooleanLiteral: /true|false/,
      StringLiteral: /\"([^"\n]|\\[\s\S])*\"|\'([^'\n]|\\[\s\S])*\'/,
      NullLiteral: /null/,
      Keywords: /if|else|for|function|let|var/,
      Identifer: /[a-zA-Z_$][a-zA-Z0-9_$]*/,
      Punctuator: /\+|\,|\?|\.|\:|\{|\}|\(|\)|\[|\]|\=|\<|\>|\+\+|\=\=|\=\>|\*|;/
    }
    // 利用 replace 替换匹配规则
    function compileRegExp(xregexp, name) {
      if (xregexp[name] instanceof RegExp) // 区分一下叶子节点和source节点
        return xregexp[name].source;
      let regexp = xregexp[name].replace(/\<([^>]+)\>/g, function(str, $1) {
        return compileRegExp(xregexp, $1)
      })
      return regexp;
    }
  
    // let regexp = compileRegExp(xregexp, "InputElement")
    // console.log(JSON.stringify(regexp))
    // console.log(new RegExp(regexp, "g"))
    
    function scan(str) {
      // let regexp = / |\n|\/\*([^*]|\*[^\/])*\*\/|\/\/[^\n]*|[1-9][0-9]*|0/g
      let regexp = new RegExp(compileRegExp(xregexp, "InputElement"), "g")
      while(regexp.lastIndex < str.length) {
        let r = regexp.exec(str)
        // console.log(r)
        document.write(r[0])
        if (!r[0].length) break;
      }
    
    }
    
    
    scan(`
      for(let i = 0; i < 3; i++) {
        for(let j = 0; j < 3; j++) {
          let cell = document.createElement("div");
          cell.classList.add("cell");
          cell.innerText = pattern[i * 3 + j] == 2 ? "❌" :
            pattern[i * 3 + j] == 1 ? "⭕" : "";
          cell.addEventListener("click", () => userMove(j, i));
          board.appendChild(cell);
        }
        board.appendChild(document.createElement("br"));
      }
    `)
    
    
  </script>
</pre>